package client;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;



/**************************************************************************************************************
 * Listens for connection on an open port and creates a client handler thread for each connecting client
 * @author Kim Persson
 *
 **************************************************************************************************************/
public class ServerClient extends Thread{
	
	private String path;
	private ServerSocket ss;
	private boolean disconnected;
	/***
	 * @param path path to shared files folder
	 * @throws IOException failed to create server socket
	 */
	public ServerClient(String path) throws IOException
	{
		this.path = path;
		disconnected = false;
		ss = new ServerSocket(0);
	}
	
	/**
	 * Gets port server socket is running on
	 * @return port number
	 */
	public int getServerPort()
	{
		return ss.getLocalPort();
	}
	
	/**
	 * Closes server socket
	 * @throws IOException failed to close socket
	 */
	public void disconnect() throws IOException
	{
		disconnected = true;
		ss.close();
	}
	
	/**
	 * Listens for connection on an open port and creates a client handler thread for each connecting client
	 */
	public void run()
	{
		try {
			
			
			while(true)
			{
				new ClientHandler(ss.accept()).start();
			}  
		} catch (IOException e) {
			if(!disconnected)
				System.out.println("ERROR: Couldn't accept incoming connection " + e.getMessage());
			else
				return;
		}
	}
	
	/**
	 * Handles client download request and transfers the file over socket
	 * @author Kim Persson
	 */
	private class ClientHandler extends Thread
	{
		private Socket s;
		/**
		 * Default constructor
		 * @param s Socket connection to handle
		 */
		public ClientHandler(Socket s)
		{
			this.s = s;
		}
		
		/**
		 * Handles client download request and transfers the file over socket
		 */
		public void run()
		{
			
			try {
				BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
				String req = br.readLine();
				
				if(req.substring(0, 7).equals("request"))
				{
					req = req.substring(8);
					File file = new File(path, secureFileName(req));
					if (file.exists())
					{
						DataInputStream dis = new DataInputStream(new FileInputStream(file));
						BufferedInputStream bis = new BufferedInputStream(dis); 
						OutputStream os = s.getOutputStream();

						int count;
						byte[] buffer = new byte[8192];
						while ((count = bis.read(buffer)) > 0)
						{
						  os.write(buffer, 0, count);
						}
						dis.close();
						os.close();
						
					}
					
					
					
				}
				
				
			} catch (IOException e) {
				System.out.println("ERROR: Couldn't send file " + e.getMessage());
			}
		}
		
		/**
		 * Removes / and \ to ensure that client can't navigate outside of shared folder
		 * @param name filname to secure
		 * @return secured filename without / and \
		 */
		private String secureFileName(String name)
		{
			return name.replace("\\", "").replace("/", "");
		}
	}
}
